﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using SubwayHelper;
using SubwayTool.Properties;

namespace SubwayTool
{
    public partial class frmSubwayHelper : Form
    {
        Point mouseDownPoint = new Point(); //记录拖拽过程鼠标位置
        bool isMove = false;    //判断鼠标在picturebox上移动时，是否处于拖拽过程(鼠标左键是否按下)
        //int zoomStep = 20;      //缩放步长
        //private Timer _timer;
        private List<QueryResult> _resultsCache = new List<QueryResult>();
        private static Point tiPoint;

        public frmSubwayHelper()
        {
            InitializeComponent();
            this.MouseWheel += FrmSubwayHelper_MouseWheel;
        }

        private void FrmSubwayHelper_MouseWheel(object sender, MouseEventArgs e)
        {
            this.picLines.Dock = DockStyle.None;
            this.picLines.BorderStyle = BorderStyle.FixedSingle;
            Size size = this.picLines.Size;
            size.Width += e.Delta;
            if (size.Width > picLines.Image.Width)
            {
                picLines.Width = picLines.Image.Width;
                picLines.Height = picLines.Image.Height;
            }
            else if (size.Width * picLines.Image.Height / picLines.Image.Width < picLines.Parent.Height - 200)
            {
                return;
            }
            else
            {
                picLines.Width = size.Width;
                picLines.Height = size.Width * picLines.Image.Height / picLines.Image.Width;
            }
            picLines.Left = (picLines.Parent.Width - picLines.Width) / 2;
            picLines.Top = (picLines.Parent.Height - picLines.Height) / 2;

        }

        private void frmSubwayHelper_Load(object sender, EventArgs e)
        {
            tiPoint = lboxTips.Location;
            cboCity.SelectedIndex = 0;
            Subway.InitSubwayLine(CityEnum.GuangZhou);
            cboDep.Focus();
        }

        private bool CheckText()
        {
            var dep = cboDep.Text.Trim();
            var dest = cboDest.Text.Trim();
            return (!string.IsNullOrWhiteSpace(dep) && !string.IsNullOrWhiteSpace(dest) && !dep.IsSame(dest));
        }

        private CityEnum _city = CityEnum.GuangZhou;
        private void btnSearch_Click(object sender, EventArgs e)
        {
            if (!CheckText()) return;
            var dep = cboDep.Text.Trim();
            var dest = cboDest.Text.Trim();
            var listResult = Subway.GetRideSubwayInfo(dep, dest, _city);
            if (listResult == null)
            {
                txtResult.Text = "始发站或到达站在线路上不存在！";
                return;
            }
            if (listResult.Count == 0)
            {
                txtResult.Text = "暂未找到乘车方案！";
                return;
            }
            _resultsCache = listResult;
            ShowResult();
        }

        private void ShowResult()
        {
            if (chkRange.Checked)
            {
                _resultsCache = _resultsCache.OrderBy(x => x.Range).ToList();
            }
            if (chkTimes.Checked)
            {
                _resultsCache = _resultsCache.OrderBy(x => x.TransferTimes).ToList();
            }
            if (chkFive.Checked)
            {
                _resultsCache = _resultsCache.Take(5).ToList();
            }
            if (chkOnlyOne.Checked)
            {
                _resultsCache = _resultsCache.Take(1).ToList();
            }
            txtResult.Text = _resultsCache.Select((x, i) => "换乘方案【" + (i + 1) + "】：\r\n" + x.Description).ToJoinString("\r\n");
        }

        private void btnChange_Click(object sender, EventArgs e)
        {
            var dep = cboDep.Text.Trim();
            cboDep.Text = cboDest.Text.Trim();
            cboDest.Text = dep;
            if (_resultsCache.Any()) btnSearch_Click(null, null);
        }

        private void pnlPic_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;
            mouseDownPoint.X = Cursor.Position.X;
            mouseDownPoint.Y = Cursor.Position.Y;
            isMove = true;
        }

        private void pnlPic_MouseMove(object sender, MouseEventArgs e)
        {
            pnlPic.Focus();
            if (!isMove) return;
            var moveX = Cursor.Position.X - mouseDownPoint.X;
            var moveY = Cursor.Position.Y - mouseDownPoint.Y;
            var x = picLines.Location.X + moveX;
            var y = picLines.Location.Y + moveY;
            picLines.Location = new Point(x, y);
            mouseDownPoint.X = Cursor.Position.X;
            mouseDownPoint.Y = Cursor.Position.Y;
        }

        private void pnlPic_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMove = false;
            }
        }

        private void chk_CheckedChanged(object sender, EventArgs e)
        {
            if (!CheckText()) return;
            btnSearch_Click(null, null);
        }

        private void cboCity_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (cboCity.Text)
            {
                case "广州":
                    _city = CityEnum.GuangZhou;
                    picLines.Image = Resources.guangzhou;
                    break;
                case "深圳":
                    _city = CityEnum.ShenZhen;
                    picLines.Image = Resources.shenzhen;
                    break;
                case "北京":
                    _city = CityEnum.BeiJing;
                    picLines.Image = Resources.beijing;
                    break;
                case "上海":
                    _city = CityEnum.ShangHai;
                    picLines.Image = Resources.shanghai;
                    break;
                case "东莞":
                    _city = CityEnum.DongGuan;
                    picLines.Image = Resources.dongguan;
                    break;
                default:
                    break;
            }
            Subway.InitSubwayLine(_city);
            cboDep.Text = cboDest.Text = txtResult.Text = "";
            cboDep.Focus();
        }

        private void chkOnlyOne_CheckedChanged(object sender, EventArgs e)
        {
            if (chkOnlyOne.Checked) chkFive.Checked = false;
            chk_CheckedChanged(null, null);
        }

        private void chkFive_CheckedChanged(object sender, EventArgs e)
        {
            if (chkFive.Checked) chkOnlyOne.Checked = false;
            chk_CheckedChanged(null, null);
        }

        List<string> GetTips(string q)
        {
            if (Subway.AllSubwayLines == null) return new List<string>();
            var source = Subway.AllSubwayLines.Select(x => x.Stations.Select(y => y.Name)).ToList();
            var tips = new List<string>();
            source.ForEach(x => tips.AddRange(x));
            tips = tips.Distinct().ToList();
            var ctips = tips.Where(x => x.Contains(q) || x.ToPinYin().Contains(q) || x.ToFirstPinyin().Contains(q)).ToList();
            //var reg = new Regex("[^a-zA-Z\r\n]+");
            // if (reg.IsMatch(q)) return ctips;
            //ctips.AddRange(from t in tips let strRoadName = Extend.GetChineseSpell(t).ToLower() where strRoadName.Contains(q) && strRoadName.Substring(0, q.Length) == q select t);
            return ctips;
        }

        private void cboStation_KeyUp(object sender, KeyEventArgs e)
        {
            //上下左右
            var sta = sender as TextBox;
            switch (e.KeyCode)
            {
                case Keys.Up:
                    //case Keys.Left:
                    if (lboxTips.SelectedIndex > 0)
                        lboxTips.SelectedIndex--;
                    break;
                case Keys.Down:
                    //case Keys.Right:
                    if (lboxTips.SelectedIndex < lboxTips.Items.Count - 1)
                        lboxTips.SelectedIndex++;
                    break;
                case Keys.Enter:
                    sta.Text = lboxTips.SelectedItem as string;
                    sta.Select(sta.Text.Length, 1);
                    lboxTips.Visible = false;
                    if (sta.Name == "cboDep")
                    {
                        cboDest.Focus();
                    }
                    else
                    {
                        btnSearch_Click(null, null);
                    }
                    break;
                default:
                    if (!string.IsNullOrWhiteSpace(sta.Text))
                    {
                        var dataSource = GetTips(sta.Text.Trim());
                        if (dataSource.Count > 0)
                        {
                            lboxTips.DataSource = dataSource;
                            lboxTips.Location = sta.Name == "cboDep" ? new Point(cboDep.Location.X + 2, cboDep.Location.Y + 25) : tiPoint;
                            lboxTips.Visible = true;
                        }
                        else
                            lboxTips.Visible = false;
                    }
                    else
                    {
                        lboxTips.Visible = false;
                    }
                    break;
            }
        }

        private void lboxTips_Click(object sender, EventArgs e)
        {
            var eObj = sender as ListBox;
            var info = eObj.SelectedItem as string;
            if (eObj.Location.Y != tiPoint.Y)
            {
                cboDep.Text = info;
                cboDest.Focus();
            }
            else
            {
                cboDest.Text = info;
                btnSearch_Click(null, null);
            }
            eObj.Visible = false;
        }

        private void lboxTips_MouseMove(object sender, MouseEventArgs e)
        {
            var eObj = sender as ListBox;
            eObj.SelectedIndex = eObj.IndexFromPoint(e.Location);
        }

        private void timerTime_Tick(object sender, EventArgs e)
        {
            label4.Text = "当前时间为：" + DateTime.Now.ToLongTimeString();//动态显示系统时间
        }
    }
}
